package com.tarena.lbs.basic.service.impl;

import com.tarena.lbs.base.protocol.exception.BusinessException;
import com.tarena.lbs.base.protocol.model.Result;
import com.alibaba.nacos.common.utils.CollectionUtils;
import com.github.pagehelper.PageInfo;
import com.tarena.lbs.base.protocol.pager.PageResult;
import com.tarena.lbs.basic.dao.repository.TagRepository;
import com.tarena.lbs.basic.pojo.param.TagUpdateParam;
import com.tarena.lbs.basic.pojo.po.TagLibraryPO;
import com.tarena.lbs.basic.pojo.query.TagQuery;
import com.tarena.lbs.basic.pojo.vo.TagLibraryVO;
import com.tarena.lbs.basic.pojo.vo.TagVO;
import com.tarena.lbs.basic.service.TagService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Slf4j
@Service
public class TagServiceImpl implements TagService  {

    @Autowired
    private TagRepository tagRepository;


    @Override
//    @Transactional(readOnly = true)
    public Map<String, List<TagVO>> getTagsByType(int i) {
        //1.从数据层 把素有的文章的标签查询 List
        List<TagLibraryPO> pos= tagRepository.getTagsBytType(i);
        log.info("查询的类型:{},查询到的标签有:{}",i,pos);
        //2.单独封装转化
        Map<String,List<TagVO>> mapVo = assembleTags2Map(pos);
        log.info("封装最终的结果map:{}",mapVo);
        return mapVo;
    }

    private Map<String, List<TagVO>> assembleTags2Map(List<TagLibraryPO> pos) {
        Map<String,List<TagVO>> mapVo=new HashMap<>();
        //2.先筛选(filter)出pos中的所有一级标签 firstLevelPos["美食","旅游"]
        List<TagLibraryPO> firstLevelPos = pos.stream().filter(po -> po.getTagParentId().equals(0)).collect(Collectors.toList());
        //3.对一级标签进行循环
        firstLevelPos.stream().forEach(firstPo->{
            String firstTagName=firstPo.getTagName();//map的key值 美食  旅游
            Integer firstTagId=firstPo.getId();//不就是 二级标签parentId
            //4.如何通过一级标签 对象 拿到属于他的二级标签列表 筛选一下parentId等于当前一级标签id的所有
            //路边摊 网红店  高档酒店
            //日记 传说 趣闻
            List<TagLibraryPO> secondLevelPos =
                    pos.stream().filter(po -> po.getTagParentId().equals(firstTagId)).collect(Collectors.toList());
            //5.将当前的二级标签pos 转化成TagVO格式
            List<TagVO> value = secondLevelPos.stream().map(po -> {
                TagVO vo = new TagVO();
                //一级标签名字
                vo.setTagCategoryName(firstTagName);
                TagLibraryVO voTag = new TagLibraryVO();
                BeanUtils.copyProperties(po, voTag);
                vo.setTagLibraryBO(voTag);
                return vo;
            }).collect(Collectors.toList());
            mapVo.put(firstTagName, value);
        });
        return mapVo;
    }

    @Override
    public TagLibraryPO getTagById(Integer id) {
        return tagRepository.getTagById(id);
    }

    @Override
    public PageResult<TagLibraryVO> getAllTags(TagQuery query) {
        PageResult<TagLibraryVO> voPage = new PageResult<>(query);
        PageInfo<TagLibraryPO> pageInfo = tagRepository.getAllTags(query);
        // 将分页信息中的页码设置到分页结果对象中
        voPage.setPageNo(pageInfo.getPageNum());
        // 将分页信息中的每页数量设置到分页结果对象中
        voPage.setPageSize(pageInfo.getPageSize());
        // 将分页信息中的总记录数设置到分页结果对象中
        voPage.setTotal(pageInfo.getTotal());
        // 声明一个存储管理员视图对象的列表
        List<TagLibraryVO> vos = null;
        // 从分页信息中获取管理员持久化对象列表
        List<TagLibraryPO> pos = pageInfo.getList();

        // 判断持久化对象列表是否不为空
        if (CollectionUtils.isNotEmpty(pos)){
            vos=pos.stream().map(po->{
                TagLibraryVO vo = new TagLibraryVO();
                BeanUtils.copyProperties(po,vo);
                return vo;
            }).collect(Collectors.toList());
        }
        voPage.setObjects(vos);
        return voPage;
    }

    @Override
    @Transactional
    public boolean addTag(TagLibraryPO tagLibraryPO) throws BusinessException {
        try {
            // 1. 验证标签名称是否已存在
            TagLibraryPO existingTag = tagRepository.getTagByNameAndType(tagLibraryPO.getTagName(), tagLibraryPO.getTagType());
            if (existingTag != null) {
                throw new BusinessException("-1", "标签名称已存在");
            }
        
            // 2. 处理标签分组逻辑
            if (tagLibraryPO.getTagParentId() != null && tagLibraryPO.getTagParentId() > 0) {
                // 检查父标签是否存在
                TagLibraryPO parentTag = tagRepository.getTagById(tagLibraryPO.getTagParentId());
                if (parentTag == null) {
                    throw new BusinessException("-1", "父标签不存在");
                }
                // 确保父标签与子标签类型一致
                if (!parentTag.getTagType().equals(tagLibraryPO.getTagType())) {
                    throw new BusinessException("-1", "父标签类型与当前标签类型不一致");
                }
            } else {
                // 如果没有父标签，设置为0表示一级标签
                tagLibraryPO.setTagParentId(0);
            }
        
            // 3. 设置创建时间和更新时间
            Date now = new Date();
            tagLibraryPO.setCreateAt(now);
            tagLibraryPO.setUpdateAt(now);
        
            // 4. 如果状态未设置，默认设置为启用
            if (tagLibraryPO.getStatus() == null) {
                tagLibraryPO.setStatus(0);
            }
        
            // 5. 如果门店状态未设置，默认设置为开启
            if (tagLibraryPO.getStoreStatus() == null) {
                tagLibraryPO.setStoreStatus(0);
            }
        
            // 6. 如果使用次数未设置，默认为0
            if (tagLibraryPO.getUsageCount() == null) {
                tagLibraryPO.setUsageCount(0);
            }
        
            // 7. 生成标签编码
            if (tagLibraryPO.getCoding() == null) {
                tagLibraryPO.setCoding(generateTagCoding());
            }
        
            // 8. 调用数据层插入标签
            int result = tagRepository.addTag(tagLibraryPO);
            return result > 0;
        } catch (BusinessException e) {
            // 已定义的业务异常，直接抛出
            throw e;
        } catch (Exception e) {
            // 未定义的异常，包装为业务异常
            throw new BusinessException("-1", "新增标签失败：" + e.getMessage());
        }
    }

    @Override
    public boolean updateTag(TagLibraryPO tagLibraryPO) {
        return false;
    }

    /**
     * 生成标签编码
     */
    private String generateTagCoding() {
        return java.util.UUID.randomUUID().toString().replace("-", "");
    }

    @Override
    public boolean updateTag(TagUpdateParam param) throws BusinessException {
        // 1. 参数校验
        if (param == null || param.getId() == null) {
            log.warn("更新标签参数为空或ID为空");
            throw new BusinessException("-1", "标签ID不能为空");
        }

        if (param.getTagName() == null || param.getTagName().trim().isEmpty()) {
            log.warn("标签名称不能为空");
            throw new BusinessException("-1", "标签名称不能为空");
        }

        // 2. 检查标签是否存在
        TagLibraryPO existingTag = tagRepository.getTagById(param.getId());
        if (existingTag == null) {
            log.warn("标签不存在，ID: {}", param.getId());
            throw new BusinessException("-1", "标签不存在");
        }

        // 3. 检查标签名称是否已存在（排除当前标签）
        TagLibraryPO tagByNameAndType = tagRepository.getTagByNameAndType(param.getTagName(), param.getTagType());
        if (tagByNameAndType != null && !tagByNameAndType.getId().equals(param.getId())) {
            log.warn("标签名称已存在: {}", param.getTagName());
            throw new BusinessException("-1", "标签名称已存在");
        }

        // 4. 处理父子标签关系
        if (param.getTagParentId() != null && param.getTagParentId() > 0) {
            TagLibraryPO parentTag = tagRepository.getTagById(param.getTagParentId());
            if (parentTag == null) {
                log.warn("父标签不存在，ID: {}", param.getTagParentId());
                throw new BusinessException("-1", "父标签不存在");
            }

            if (param.getTagType() != null && !parentTag.getTagType().equals(param.getTagType())) {
                log.warn("父子标签类型不一致");
                throw new BusinessException("-1", "父标签类型与当前标签类型不一致");
            }
        } else if (param.getTagParentId() != null) {
            // 如果没有父标签，设置为0表示一级标签
            param.setTagParentId(0);
        }

        // 5. 转换参数到PO对象
        TagLibraryPO tagLibraryPO = assembleTagPO(param, existingTag);

        // 6. 执行更新操作
        int result = tagRepository.updateTag(tagLibraryPO);
        log.info("标签更新完成，ID: {}, 影响行数: {}", param.getId(), result);

        return result > 0;
    }

    /**
     * 将更新参数转换为数据库实体对象
     */
    private TagLibraryPO assembleTagPO(TagUpdateParam param, TagLibraryPO existingTag) {
        TagLibraryPO po = new TagLibraryPO();
        // 复制现有标签的所有属性
        BeanUtils.copyProperties(existingTag, po);

        // 更新字段
        po.setTagName(param.getTagName());

        if (param.getTagType() != null) {
            po.setTagType(param.getTagType());
        }

        if (param.getTagParentId() != null) {
            po.setTagParentId(param.getTagParentId());
        }

        if (param.getCoding() != null) {
            po.setCoding(param.getCoding());
        }

        if (param.getTagDesc() != null) {
            po.setTagDesc(param.getTagDesc());
        }

        if (param.getStatus() != null) {
            po.setStatus(param.getStatus());
        }

        if (param.getStoreStatus() != null) {
            po.setStoreStatus(param.getStoreStatus());
        }

        // 设置更新时间
        po.setUpdateAt(new Date());

        return po;
    }


    @Override
    public Result<Void> deleteTag(Integer id) {
        if (id == null || id <=0) {
            return Result.fail("-1","标签ID不能为空");
        }
        //检查标签是否存在
        TagLibraryPO tagPO = tagRepository.getTagById(id);
        if (tagPO == null){
            return Result.fail("-1","标签不存在");
        }

        //执行假删除
        int rows = tagRepository.deleteTag(id);
        if (rows <= 0){
            return Result.fail("-1","删除失败");
        }
        return Result.success();
    }

    @Override
    public List<TagLibraryPO> getTagsByParentId(Integer parentId) {
        return tagRepository.getTagsByParentId(parentId);
    }

}